package com.jincheng.system.service.impl;

import com.baomidou.mybatisplus.core.batch.MybatisBatch;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jincheng.common.core.domain.entity.SysUser;
import com.jincheng.common.utils.DateUtils;
import com.jincheng.system.domain.Activity;
import com.jincheng.system.domain.SysNotice;
import com.jincheng.system.domain.Tribe;
import com.jincheng.system.domain.dto.UserTribeDetailDTO;
import com.jincheng.system.mapper.SysNoticeMapper;
import com.jincheng.system.mapper.TribeMapper;
import com.jincheng.system.service.ISysNoticeService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.SerializationUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.jincheng.common.utils.SecurityUtils.getLoginUser;
import static com.jincheng.common.utils.SecurityUtils.getUsername;

/**
 * 公告 服务层实现
 *
 * @author DairyJay
 */
@RequiredArgsConstructor
@Service
public class SysNoticeServiceImpl implements ISysNoticeService {
    private final SysNoticeMapper noticeMapper;
    private final SqlSessionFactory sqlSessionFactory;
    private final TribeMapper tribeMapper;

    /**
     * 查询公告信息
     *
     * @param noticeId 公告ID
     * @return 公告信息
     */
    @Override
    public SysNotice selectNoticeById(Long noticeId) {
        return noticeMapper.selectNoticeById(noticeId);
    }

    /**
     * 查询公告列表
     *
     * @param notice 公告信息
     * @return 公告集合
     */
    @Override
    public List<SysNotice> selectNoticeList(SysNotice notice) {
        LambdaQueryWrapper<SysNotice> queryWrapper = new LambdaQueryWrapper<>();
        if (notice.getNoticeId() != null && notice.getNoticeId() > 0)
            queryWrapper.eq(SysNotice::getNoticeId, notice.getNoticeId());

        if (notice.getNoticeTitle() != null && !"".equals(notice.getNoticeTitle()))
            queryWrapper.like(SysNotice::getNoticeTitle, notice.getNoticeTitle());

        if (notice.getNoticeType() != null)
            queryWrapper.eq(SysNotice::getNoticeType, notice.getNoticeType());

        if (notice.getSimpleInfo() != null && !notice.getSimpleInfo().isEmpty())
            queryWrapper.like(SysNotice::getSimpleInfo, notice.getSimpleInfo());

        if (notice.getNoticeContent() != null && !notice.getNoticeContent().isEmpty())
            queryWrapper.like(SysNotice::getNoticeContent, notice.getNoticeContent());

        if (notice.getStatus() != null && !notice.getStatus().isEmpty())
            queryWrapper.eq(SysNotice::getStatus, notice.getStatus());

        if (notice.getToUser() != null)
            queryWrapper.eq(SysNotice::getToUser, notice.getToUser());

        if (notice.getIsRead() != null)
            queryWrapper.eq(SysNotice::getIsRead, notice.getIsRead());

        return noticeMapper.selectList(queryWrapper);
    }

    /**
     * 新增公告
     *
     * @param notice 公告信息
     * @return 结果
     */
    @Override
    public int insertNotice(SysNotice notice) {
        return noticeMapper.insertNotice(notice);
    }

    /**
     * 批量新增公告
     *
     * @param noticeList 公告信息列表
     * @return 结果
     */
    @Override
    public int insertBachNotice(List<SysNotice> noticeList) {
        MybatisBatch<SysNotice> mybatisBatch = new MybatisBatch<>(sqlSessionFactory, noticeList);
        MybatisBatch.Method<SysNotice> method = new MybatisBatch.Method<>(SysNoticeMapper.class);
        return mybatisBatch.execute(method.insert()).size();
    }

    /**
     * 修改公告
     *
     * @param notice 公告信息
     * @return 结果
     */
    @Override
    public int updateNotice(SysNotice notice) {
        return noticeMapper.updateNotice(notice);
    }

    /**
     * 删除公告对象
     *
     * @param noticeId 公告ID
     * @return 结果
     */
    @Override
    public int deleteNoticeById(Long noticeId) {
        return noticeMapper.deleteNoticeById(noticeId);
    }

    /**
     * 批量删除公告信息
     *
     * @param noticeIds 需要删除的公告ID
     * @return 结果
     */
    @Override
    public int deleteNoticeByIds(Long[] noticeIds) {
        return noticeMapper.deleteNoticeByIds(noticeIds);
    }

    /**
     * 修改公告已读状态
     *
     * @param noticeIds 公告id列表
     * @return 结果
     */
    @Override
    public int updateNoticeReadStates(List<Long> noticeIds) {

        LambdaUpdateWrapper<SysNotice> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.in(SysNotice::getNoticeId, noticeIds);
        updateWrapper.set(SysNotice::getIsRead, true);

        return noticeMapper.update(updateWrapper);
    }


    /**
     * 发送活动报名通知
     *
     * @param activity 活动信息
     */
    @Override
    public void sendActivityApplyNotice(Activity activity) {
        Tribe tribe = tribeMapper.selectById(activity.getTribeId());
        SysUser user = getLoginUser().getUser();
        SysNotice notice = getNotice();

        notice.setNoticeTitle("活动审核通知");
        notice.setSimpleInfo("您收到了来自活动\"" + activity.getActivityName() + "\"的报名信息，请前往审核。");
        notice.setNoticeContent(getActivityApplyHtml(activity, user));
        notice.setToUser(tribe.getChairId());
        noticeMapper.insert(notice);
    }

    /**
     * 发送活动报名通过通知
     *
     * @param activity   活动信息
     * @param userIdList 用户id列表
     */
    @Override
    public void sendActivityApplyPassNotice(Activity activity, List<Long> userIdList) {
        SysNotice sysNotice = getNotice();
        sysNotice.setNoticeTitle("活动报名通过");
        sysNotice.setSimpleInfo("您报名的活动\"" + activity.getActivityName() + "\"已被通过审核，请准时参与。");
        sysNotice.setNoticeContent(getActivityApplyPassHtml(activity));
        sendActivityWhetherApplyPass(activity, userIdList, sysNotice);
    }

    /**
     * 发送活动报名未通过通知
     *
     * @param activity   活动信息
     * @param userIdList 用户id列表
     */
    @Override
    public void sendActivityApplyFailNotice(Activity activity, List<Long> userIdList) {
        SysNotice sysNotice = getNotice();
        sysNotice.setNoticeTitle("活动报名失败");
        sysNotice.setSimpleInfo("您报名的活动\"" + activity.getActivityName() + "\"已被拒绝，请重新报名。");
        sysNotice.setNoticeContent(getActivityApplyFailHtml(activity));
        sendActivityWhetherApplyPass(activity, userIdList, sysNotice);
    }

    private void sendActivityWhetherApplyPass(Activity activity, List<Long> userIdList, SysNotice sysNotice) {
        List<SysNotice> sysNoticeList = new ArrayList<>();
        for (Long userId : userIdList) {
            SysNotice cloneNotice = SerializationUtils.clone(sysNotice);
            cloneNotice.setToUser(userId);
            sysNoticeList.add(cloneNotice);
        }
        insertBachNotice(sysNoticeList);
    }

    /**
     * 发送部落申请通知
     *
     * @param tribe 部落信息
     */
    @Override
    public void sendTribeApplyNotice(Tribe tribe) {
        SysNotice notice = getNotice();
        String contentHtml = getTribeApplyHtml(tribe);

        notice.setNoticeTitle("部落申请通知");
        notice.setSimpleInfo("您收到了一条来自部落\"" + tribe.getTribeName() + "\"的申请信息，请前往审核");
        notice.setNoticeContent(contentHtml);
        notice.setToUser(tribe.getChairId());
        noticeMapper.insert(notice);
    }

    /**
     * 发送部落申请通过通知
     *
     * @param userTribeDetailDTO 用户信息
     */
    @Override
    public void sendTribeApplyPassNotice(UserTribeDetailDTO userTribeDetailDTO) {
        SysNotice notice = getNotice();
        notice.setToUser(userTribeDetailDTO.getUserId());
        notice.setRemark(userTribeDetailDTO.getRemark());
        // 发送通知
        if (userTribeDetailDTO.getStatus() == 0) {
            notice.setNoticeTitle("部落申请通过");
            notice.setSimpleInfo("您申请加入的部落\"" + userTribeDetailDTO.getTribeName() + "\"已被通过审核，请加入部落。");
            notice.setNoticeContent(getTribeApplyPassHtml(userTribeDetailDTO.getTribeName(), null));
        } else {
            notice.setNoticeTitle("部落申请未通过");
            notice.setSimpleInfo("您申请加入的部落\"" + userTribeDetailDTO.getTribeName() + "\"已被拒绝，请重新申请。");
            notice.setNoticeContent(getTribeApplyPassHtml(userTribeDetailDTO.getTribeName(), userTribeDetailDTO.getRemark()));
        }

        noticeMapper.insert(notice);
    }


    /**
     * 获取包含更新时间和更新者的通知对象
     *
     * @param noticeType 通知类型
     * @return 通知对象
     */
    private SysNotice getNotice(Integer noticeType) {
        SysNotice notice = new SysNotice();
        notice.setNoticeType(noticeType);
        notice.setCreateBy(getUsername());
        notice.setCreateTime(DateUtils.getNowDate());
        notice.setUpdateBy(getUsername());
        notice.setUpdateTime(DateUtils.getNowDate());
        return notice;
    }

    /**
     * 获取通知对象
     */
    private SysNotice getNotice() {
        return getNotice(1);
    }

    /**
     * 获取公告通知对象
     */
    private SysNotice getAnnouncement() {
        return getNotice(2);
    }

    /**
     * 获取活动报名通知html
     *
     * @param activity 活动信息
     * @param user     用户信息
     * @return html
     */
    private static String getActivityApplyHtml(Activity activity, SysUser user) {
        String dateTime = DateUtils.getDateTime();
        return "<p>通知时间:" + dateTime + "</p>"
                + "<h2>新报名审核通知</h2>"
                + "<p>尊敬的活动管理员，</p>"
                + "<p>您有一条新的活动报名申请，详情如下：</p>"
                + "<ul>"
                + "<li><strong>用户姓名：</strong>" + user.getNickName() + "</li>"
                + "<li><strong>报名活动：</strong>" + activity.getActivityName() + "</li>"
                + "<li><strong>报名时间：</strong>" + dateTime + "</li>"
                + "<li><strong>备注：</strong></li>"
                + "</ul>"
                + "<p>请您尽快登录系统审核该申请</p>"
                + "<p>注意：请在"
                + DateUtils.dateTime(activity.getApplyEndTime())
                + "前完成审核，以确保活动顺利开展。</p>"
                + "<p>谢谢！</p>";
    }

    /**
     * 获取活动报名通过通知html
     *
     * @param activity 活动信息
     * @return html
     */
    private static String getActivityApplyPassHtml(Activity activity) {
        String dateTime = DateUtils.dateTime(activity.getStartTime())
                + " - " + DateUtils.dateTime(activity.getEndTime());

        return "<p>通知时间:" + DateUtils.getDateTime() + "</p>"
                + "<h2>报名通过通知</h2>"
                + "<p>尊敬的用户:</p>"
                + "<p>您的报名申请已被管理员审核通过，请及时前往活动地点进行签到。</p>"
                + "<p>活动信息如下：</p>"
                + "<ul>"
                + "<li><strong>活动名称：</strong>" + activity.getActivityName() + "</li>"
                + "<li><strong>活动地点：</strong>" + activity.getAddress() + "</li>"
                + "<li><strong>活动时间：</strong>" + dateTime + "</li>"
                + "<p>请及时前往活动地点进行签到</p>"
                + "<p>注意：请在"
                + DateUtils.dateTime(activity.getEndTime())
                + "前完成签到" + (activity.getIsCheck() ? "/签退，" : ",")
                + "以确保活动顺利开展。</p>"
                + "<p>谢谢！</p>";
    }


    /**
     * 获取活动报名失败通知html
     *
     * @param activity 活动信息
     * @return html
     */
    private static String getActivityApplyFailHtml(Activity activity) {
        return "<p>通知时间:" + DateUtils.getDateTime() + "</p>"
                + "<h2>报名失败通知</h2>"
                + "<p>尊敬的用户:</p>"
                + "<p>您的报名的活动"
                + activity.getActivityName()
                + "已被管理员审核不通过，请重新报名。</p>";
    }

    /**
     * 获取部落申请通知html
     *
     * @param tribe 部落信息
     * @return html
     */
    private static String getTribeApplyHtml(Tribe tribe) {
        SysUser user = getLoginUser().getUser();
        return "<p>通知时间:" + DateUtils.getDateTime() + "</p>"
                + "<h2>部落申请通知</h2>"
                + "<p>尊敬的用户:</p>"
                + "<p>您收到了一条来自部落\"" + tribe.getTribeName() + "\"的申请信息</p>"
                + "<p>申请人信息：</p>"
                + "<ul>"
                + "<li><strong>用户姓名: </strong>" + user.getNickName() + "</li>"
                + "<li><strong>用户学号: </strong>" + user.getStudentNumber() + "</li>"
                + "<li><strong>用户专业: </strong>" + user.getDept().getDeptName() + "</li>"
                + "<li><strong>用户年级: </strong>" + user.getGrade() + "</li>"
                + "</ul>"
                + "<p>请及时前往审核</p>";
    }

    /**
     * 构建部落申请结果html
     *
     * @param tribeName 部落名称
     * @param reason    拒绝理由，null表示通过
     * @return html
     */
    private String getTribeApplyPassHtml(String tribeName, String reason) {
        return "<p>通知时间:" + DateUtils.getDateTime() + "</p>"
                + "<h2>部落申请结果通知</h2>"
                + "<p>尊敬的用户:</p>"
                + "<p>您申请加入的部落\"" + tribeName + "\"已于"
                + DateUtils.getDateTime() + "被" + (reason == null ? "通过" : "拒绝")
                + (reason == null ? "<p>您可以在我的部落中查看部落信息</p>" : "<p>拒绝理由：" + reason + "</p>");
    }

}
